package cn.yzgy.yzgyoa.ucenter.service.impl;

import cn.yzgy.yzgyoa.ucenter.dto.OnlineUserDto;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * 在线用户服务
 *
 * @author Yqsen
 * @since 2019-12-19 10:26:22
 */
@Slf4j
@Service
public class SysOnlineUserService {

    private final SysUserDetailServiceImpl sysUserDetailService;
    private final SessionDAO sessionDAO;

    public SysOnlineUserService(SysUserDetailServiceImpl sysUserDetailService, SessionDAO sessionDAO) {
        this.sysUserDetailService = sysUserDetailService;
        this.sessionDAO = sessionDAO;
    }

    /**
     * 获取在线用户列表
     *
     * @return 在线用户列表
     */
    public List<OnlineUserDto> getOnlineUsers() {
        List<OnlineUserDto> onlineUsers = new ArrayList<>();
        sessionDAO.getActiveSessions().forEach(x -> onlineUsers.add(OnlineUserDto.trans(x, sysUserDetailService)));
        return onlineUsers;
    }

    /**
     * 将用户踢下线
     *
     * @param loginName 用户登录名
     * @return true false
     */
    public boolean kickUser(String loginName) {
        List<Session> sessions = getUserSession(loginName);
        if (sessions.size() != 0) {
            sessions.forEach(sessionDAO::delete);
            log.info("用户：{} 强制下线", loginName);
            return true;
        }
        return false;
    }

    /**
     * 将除了当前会话外的所有此用户的会话踢下线
     *
     * @param loginName 用户登录名
     * @param sessionId 要保留的SessionID
     */
    public void kickUser(String loginName, String sessionId) {
        List<Session> sessions = getUserSession(loginName);
        sessions.forEach(x ->{
            if (!x.getId().equals(sessionId)) {
                sessionDAO.delete(x);
                log.info("用户：{} 其余会话已强制下线", loginName);
            }
        });
    }

    /**
     * 获取用户Session
     *
     * @param loginName 用户登录名
     * @return 用户Session或null
     */
    public List<Session> getUserSession(String loginName) {
        final String loginNameKeyName = "loginName";
        List<Session> listOfSession = new ArrayList<>();
        for (Session x : sessionDAO.getActiveSessions()) {
            JSONObject object = (JSONObject)JSONObject.toJSON(x.getAttribute(OnlineUserDto.ATTRIBUTE_KEY));
            JSONObject principal = (JSONObject) JSONObject.toJSON(object.get(OnlineUserDto.PRIMARY_PRINCIPAL_KEY));
            if (principal.getString(loginNameKeyName).equals(loginName)) {
                listOfSession.add(x);
            }
        }
        return listOfSession;
    }


}
